package pilegen;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.awt.font.TextAttribute;

import javax.swing.JPanel;

import com.mxgraph.model.mxCell;
import com.mxgraph.model.mxGeometry;
import com.mxgraph.swing.mxGraphComponent;
import com.mxgraph.util.mxConstants;
import com.mxgraph.util.mxPoint;
import com.mxgraph.util.mxRectangle;
import com.mxgraph.view.mxEdgeStyle;
import com.mxgraph.view.mxGraph;

public class DrawEnvironnementBis extends Component {
	
	private static final long serialVersionUID = 1L;
    public static int sizeRectX = 200;
    public static int ecartX = 70;
    public static int sizeRectY = 90;
    public static int sizeLineY = 12;
	final int PORT_DIAMETER = 20;
	final int PORT_RADIUS = PORT_DIAMETER / 2;
	
	public DrawEnvironnementBis() {
		super();
		mxGraph graph = new mxGraph() {
			// Ports are not used as terminals for edges, they are
			// only used to compute the graphical connection point
			public boolean isPort(Object cell) {
				mxGeometry geo = getCellGeometry(cell);
				return (geo != null) ? geo.isRelative() : false;
			}
			// Implements a tooltip that shows the actual
			// source and target of an edge
			public String getToolTipForCell(Object cell){
				if (model.isEdge(cell)){
					return convertValueToString(model.getTerminal(cell, true)) + " -> " +
						convertValueToString(model.getTerminal(cell, false));
				}
				return super.getToolTipForCell(cell);
			}
			// Removes the folding icon and disables any folding
			public boolean isCellFoldable(Object cell, boolean collapse){
				return false;
			}
		};
		// Sets the default edge style
		//Map<String, Object> style = graph.getStylesheet().getDefaultEdgeStyle();
		//style.put(mxConstants.STYLE_EDGE, mxEdgeStyle.ElbowConnector);
		Object parent = graph.getDefaultParent();
		graph.getModel().beginUpdate();
		try{
			/* on affiche les poignees */
			System.out.println("Taille pile : "+GUI.paint.env.pile.size());
			for(int i = 0; i<GUI.paint.env.pile.size();i++){
				mxCell vi = (mxCell) graph.insertVertex(parent, null, GUI.paint.env.pile.get(i).nom,
						0, i*16, 40, 16, "");
				System.out.println("Le label du noeud est "+graph.getLabel(vi));
				vi.setConnectable(false);
				mxGeometry geo = graph.getModel().getGeometry(vi);
			}
			
			/* on affiche les variables */
			ArrayList<Integer> cpt = new ArrayList<Integer>();
			for(int k=0; k<GUI.paint.env.types.size(); k++){
				cpt.add(0);
			}
			for(int i = 0; i<GUI.paint.env.instances.size();i++){
				Variable var_i = GUI.paint.env.instances.get(i);
				int row = 0;
				boolean classeDessinable = false;
				for(int j = 0; j<GUI.paint.env.types.size(); j++){
					if(GUI.paint.env.types.get(j).getName().equals(var_i.type.getName())){
						row = j;
						classeDessinable = true;
					}
				}
				/* une variable dont le type ne figure pas parmi les classes dans env.types ne sera pas affichee */
				if(classeDessinable){
					int xdep = (row+1)*sizeRectX+((cpt.get(row))%2)*10;
					int ydep = cpt.get(row)*sizeRectY + 20;
					//int ydep = cpt.get(row)*25*(env.instances.get(i).type.getDeclaredFields().length+1 )+ 40;
					var_i.xaff = xdep;
					var_i.yaff = ydep;
					cpt.set(row, cpt.get(row)+1);
					Field[] allFields = Environnement.getAllFields(var_i.type);
					/* identifiant du noeud ou vertex */
					String nomVar_i = var_i.name;
					mxCell vi = (mxCell) graph.insertVertex(parent, null, nomVar_i,
							xdep, ydep, sizeRectX - ecartX, sizeLineY*(allFields.length+2), "");
					vi.setConnectable(false);
					mxGeometry geo = graph.getModel().getGeometry(vi);
					for(int j=0; j < allFields.length; j++){
						/* affichage de chaque attribut */
						String typeatt = allFields[j].getType().getSimpleName();
						String nomatt = allFields[j].getName();
						String typeAttComplet = allFields[j].getType().getName();
						int modifier = allFields[j].getModifiers();
						String prefix = "";
						if(Modifier.isPublic(modifier)){
							prefix = "+";
						}else if(Modifier.isPrivate(modifier)){
							prefix = "-";
						}else if(Modifier.isProtected(modifier)){
							prefix = "#";
						}
						String suffix = "";
						/* affichage des valeurs des types primitifs */
						if(typeAttComplet.equals("java.lang.Integer") || typeAttComplet.equals("int")){
							Variable valVar = GUI.paint.env.getVariableByName(var_i.name+"."+allFields[j].getName());
							if(valVar!=null && valVar.valeur!=null){
								suffix = " = "+valVar.valeur;
							}
						}else if(typeAttComplet.equals("java.lang.String")){
							Variable valVar = GUI.paint.env.getVariableByName(var_i.name+"."+allFields[j].getName());
							if(valVar!=null && valVar.valeur!=null){
								suffix = " = \""+valVar.valeur+"\"";
							}
						}
						mxGeometry geoj = new mxGeometry(0.9, (new Double(j))/(new Double(allFields.length)),
								PORT_DIAMETER, PORT_DIAMETER);
						geoj.setOffset(new mxPoint(-PORT_RADIUS, -PORT_RADIUS));
						geoj.setRelative(true);
						mxCell portj = new mxCell(null, geoj, "shape=ellipse;perimter=ellipsePerimeter");
						portj.setVertex(true);
						graph.cellLabelChanged(portj, var_i.name+"."+nomatt, false);
						graph.addCell(portj, vi);
						
					}
				}
			}
			
			/* liens entre poignees et variables */
			Object[] cells =  graph.getChildCells(graph.getDefaultParent(),true,true);
			for(int i=0; i<GUI.paint.env.pile.size(); i++){
				if(GUI.paint.env.pile.get(i).pointeVers!=null){
					Object noeudPoignee = null;
					Object noeudPointe = null;
					String pointname = GUI.paint.env.pile.get(i).pointeVers.name;
					for (Object vertex: cells){
						if(graph.getLabel(vertex).equals(pointname)){
							noeudPointe = vertex;
						}
						if(graph.getLabel(vertex).equals(GUI.paint.env.pile.get(i).nom)){
							noeudPoignee = vertex;
						}
					}
					if(noeudPoignee!=null && noeudPointe!=null){
						graph.insertEdge(parent, null, "", noeudPoignee, noeudPointe);
					}
				}
			}
			
			/* liens entre attributs et variables */
			for(int i = 0; i<GUI.paint.env.instances.size(); i++){
				Variable var_i = GUI.paint.env.instances.get(i);
				Object noeudVar_i = null;
				for(Object vertex : cells ){
					if(graph.getLabel(vertex).equals(var_i.name)){
						noeudVar_i = vertex;
					}
				}
				if((noeudVar_i!=null) && (GUI.paint.env.isDrawable(var_i.type.getName()))){
					//int xdep = var_i.xaff;
					//int ydep = var_i.yaff;
					System.out.println("Lien entre "+graph.getLabel(noeudVar_i)+" et ses attributs");
					for(int j=0; j<var_i.variablesMeres.size(); j++){
						Variable varMere = GUI.paint.env.getVariableByName(var_i.variablesMeres.get(j).name);
						Object noeudVarMere = null;
						for(Object vertex : cells){
							if(graph.getLabel(vertex).equals(varMere.name)){
								noeudVarMere = vertex;
							}
						}
						if(noeudVarMere!=null){
							Object[] cellsFils =  graph.getChildCells(noeudVarMere,true,true);
							String nomNoeudPere = varMere.name+"."+var_i.attributsPeres.get(j);
							System.out.println("Quel noeud correspond a l'attribut "+nomNoeudPere+" ????");
							
							for(Object vertex : cellsFils){
								System.out.println("Est-ce lui : "+graph.getLabel(vertex));
								if(graph.getLabel(vertex).equals(nomNoeudPere)){
									System.out.println("OUI");
									graph.insertEdge(parent, null, "", vertex, noeudVar_i);
								}else{
									System.out.println("NON");
								}
							}
						}
					}
				}
			}
		}finally{
			graph.getModel().endUpdate();
			
		}
		mxGraphComponent graphComponent = new mxGraphComponent(graph);
		BorderLayout layout = (BorderLayout) GUI.homescreen.getContentPane().getLayout();
		GUI.homescreen.remove(layout.getLayoutComponent(BorderLayout.CENTER));
		GUI.homescreen.getContentPane().add(graphComponent, BorderLayout.CENTER);
		graphComponent.setToolTips(true);
	}

    
	/*
	@Override
	public Dimension getPreferredSize() {	
		return new Dimension(env.types.size()*(sizeRectX+60), 600);
	}*/
	
	/*private void drawBackground(Graphics2D g2) {
		g2.setColor(Color.WHITE);
		Dimension size = getPreferredSize();
		g2.fillRect(0, 0, size.width, size.height);
	}	
	*/
}

